// 基于 SnowLang Project (https://gitee.com/jcnc-org/snow) 的衍生作品
// 原始版权归属: Copyright © 2025 Ke Xu (Luke)
// 本实现版权归属: Copyright © 2025 Sany
// 遵循 Apache License 2.0 授权
package execution

import (
	"fmt"

	"gitee.com/xntk2381/cc/vm/factories"
	"gitee.com/xntk2381/cc/vm/module"
)

/**
 * Command Execution Handler (CommandExecutionHandler)
 * <p>
 * This class is responsible for invoking the appropriate command object based on the opcode
 * and executing the command logic. It retrieves specific command instances through the {@link CommandFactory},
 * and calls the {@code execute} method of the command to handle the virtual machine's instruction execution process.
 * </p>
 */
type CommandExecutionHandler struct {
	operandStack       *module.OperandStack
	localVariableStore *module.LocalVariableStore
	callStack          *module.CallStack
}

/**
 * Constructor to initialize the command execution handler.
 *
 * @param operandStack       The stack manager used to manage the virtual machine's stack data.
 * @param localVariableStore The local variable table used to store the local variables used during instruction execution.
 * @param callStack          The call stack used to manage the method invocation hierarchy during execution.
 */
func NewCommandExecutionHandler(
	operandStack *module.OperandStack,
	localVariableStore *module.LocalVariableStore,
	callStack *module.CallStack,
) *CommandExecutionHandler {
	return &CommandExecutionHandler{
		operandStack:       operandStack,
		localVariableStore: localVariableStore,
		callStack:          callStack,
	}
}

/**
 * Handles the given instruction operation.
 * <p>
 * This method retrieves the corresponding command instance based on the passed opcode
 * and executes it. If the command is invalid or an error occurs during execution,
 * an error message is printed, and -1 is returned to indicate that the program should terminate or an error occurred.
 * </p>
 *
 * @param opCode    The opcode representing the type of instruction to execute (e.g., PUSH, POP, ADD, etc.).
 * @param parts     The array of parameters for the instruction, for example, `10` in `PUSH 10` is the parameter.
 * @param currentPC The current Program Counter (PC) indicating the current instruction's position.
 * @return The address of the next instruction to execute. A return value of -1 indicates termination or an error.
 * @throws IllegalArgumentException If the opcode is invalid, this exception will be thrown.
 */

func (h *CommandExecutionHandler) Handle(opCode int, parts []string, currentPC int) (int, error) {
	command, err := factories.GetInstruction(opCode)
	if err != nil {
		fmt.Printf("Command execution error (PC=%d) -> %v\n", currentPC, err)
		return -1, err // 让VM主循环安全终止
	}

	currentLVS, err := h.callStack.PeekFrame()
	if err != nil {
		fmt.Printf("Command execution error (PC=%d) -> %v\n", currentPC, err)
		return -1, err
	}

	return command.Execute(parts, currentPC, h.operandStack, currentLVS.GetLocalVariableStore(), h.callStack)
}
